package com.dldata.devtools30.utils.security;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.crypto.*;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.*;
import java.security.spec.InvalidKeySpecException;

public class CypherStreamUtil {

    private final static Log log = LogFactory.getLog(CypherStreamUtil.class);

    public static void main(String[] args) {
        String infile = "D:\\a.txt";
        String outfile = "D:\\a.des";
        String password = "This is my key";
//        byte[] salt = initSalt();
//        encryptFile(infile, outfile, password, salt);

        infile = "D:\\a.des";
        outfile = "D:\\a.out";
//        decryptFile(infile, outfile, password, salt);
    }

    public static void decryptFile(InputStream fin, OutputStream fout, String password, byte[] salt) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException, InvalidKeyException, InvalidKeySpecException {

        byte[] desKeyData = password.getBytes();
        try {

//            Provider sunJce = new com.sun.crypto.provider.SunJCE();
//            Security.addProvider(sunJce);

            //创建密钥
            char[] pbeKeyData = password.toCharArray();
            PBEKeySpec pbeKeySpec = new PBEKeySpec(pbeKeyData);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
            SecretKey pbeKey = keyFactory.generateSecret(pbeKeySpec);
            PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);

            //解密
            Cipher pbe = Cipher.getInstance("PBEWithMD5AndDES");
            pbe.init(Cipher.DECRYPT_MODE, pbeKey, paramSpec);
            CipherOutputStream cout = new CipherOutputStream(fout, pbe);

            byte[] input = new byte[64];
            int len = 0;
            while ((len = fin.read(input)) != -1) {
                cout.write(input, 0, len);
            }
            cout.flush();
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            throw  e;
        }
    }

    public static void encryptFile(InputStream fin, OutputStream fout, String password, byte[] salt) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException, InvalidKeyException, InvalidKeySpecException {
        byte[] desKeyData = password.getBytes();
        try {
//            Provider sunJce = new com.sun.crypto.provider.SunJCE();
//            Security.addProvider(sunJce);

            //创建密钥
            char[] pbeKeyData = password.toCharArray();
            PBEKeySpec pbeKeySpec = new PBEKeySpec(pbeKeyData);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
            SecretKey pbeKey = keyFactory.generateSecret(pbeKeySpec);
            PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);

            //加密
            Cipher pbe = Cipher.getInstance("PBEWithMD5AndDES");
            pbe.init(Cipher.ENCRYPT_MODE, pbeKey, paramSpec);
            CipherOutputStream cout = new CipherOutputStream(fout, pbe);

            byte[] input = new byte[64];
            int len = 0;
            while ((len = fin.read(input)) != -1) {
                cout.write(input, 0, len);
            }
            cout.flush();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw  e;
        }
    }
}
